/*****************************************************************
                        Feedback, q=1
PURPOSE: This is the algorithm for feedback CPU scheduling. It inherits 
data and functionalities from base class Scheduler.
*****************************************************************/
import java.util.ArrayList;

public class FB1 extends Scheduler implements Runnable {

   /*--------------------------------------------------------
                        Constructor
   PURPOSE:  To ask help from views, set up data, and begin simulation
   PARAMTERS: references the input queue, stats and anime view. gets 
   value of starting clock time.
   --------------------------------------------------------*/
   public FB1(ArrayList<Process> q, statsFrame s, animeFrame a, inputFrame i, int c) {
      super(q,s,a,i,c);      
    
      thread = new Thread(this,"FB1");
      thread.start();
   } // constructor

   /*--------------------------------------------------------
                        Thread Run
   PURPOSE:  To run light-weight thread simulation
   --------------------------------------------------------*/
   public void run() {
      int all=queue.size(), interval=0, next=0;
      boolean interrupt = false;
      ArrayList<Process> readyQ1 = new ArrayList<Process>();

      do {
         clock++;
         T = processready(clock);
         if (T != null) {
            readyQueue.add(T);
            queue.remove(T);
            an.upstatus("Time "+T.getArrival()+":Process "+T.getName()+" ready.");
            try { Thread.sleep(1000); } catch (InterruptedException e) {};
         } // put in ready queue
         if (idle || interrupt) {
            if (interrupt) {
               interrupt = false;
               interval = 0;
            } // reset interval
            if (readyQueue.size()!=0)
               P = (Process)readyQueue.get(0);
            else if (readyQ1.size()!=0) {                                 
               if (next < readyQ1.size()-1)
                  next++;
               else
                  next=0;
               if (P==(Process)readyQ1.get(next))
                  if (next<readyQ1.size()-1)
                     next++;
                  else
                     next=0;
               P = (Process)readyQ1.get(next);
            } // get process from RQ1
            else
               continue;
            idle = false;                       
         } // get next process
         P.servicing();
         interval++;
         an.drawbar(P,clock);
         an.upstatus("Time "+clock+":Serving process "+P.getName()+".");
         try { Thread.sleep(1000); } catch (InterruptedException ex) {};
         if (P.getTminus()==0) {
            an.upstatus("Time "+(clock+1)+":Process "+P.getName()+" done.");
            try { Thread.sleep(1000); } catch (InterruptedException e) {};
            P.report(clock+1); // anticipate completion
            finishQueue.add(P);
            int I = search(P, readyQueue, readyQ1);
            if (I==0)
               readyQueue.remove(P);
            else if (I==1) {
               next--; // recenter ptr
               readyQ1.remove(P);
            } // readjust RQ1
            idle = true;            
            interval=0;
         } // put in finish queue
         else if (interval==1)
            if (search(P,readyQueue,readyQ1)==0) {
               readyQueue.remove(P);
               readyQ1.add(P);
            } // relegate process
            interrupt = true;                    
      } while (finishQueue.size()<all);
      an.upstatus("Algorithm finished.");
      st.report(finishQueue,"Feedback,q = 1");
      in.resetGUI();
   } // run thread

   /*--------------------------------------------------------
                        Search utility
   PURPOSE:  To determine which queue a process is in
   PARAMTERS: references process to be found and possible queues to find it in
   --------------------------------------------------------*/   
   private int search(Process A, ArrayList<Process> q0, ArrayList<Process> q1) {
      for (int j=0; j<q0.size(); j++)
         if (A==(Process)q0.get(j))
            return 0;
      for (int j=0; j<q1.size(); j++)
         if (A==(Process)q1.get(j))
            return 1;
      return -1; // shouldn't happen
   } // determines which queue 

} // FB1 class
